<?php
declare (strict_types = 1);

namespace app\admin\service;

use think\Db;
use think\Request;
use think\Session;

/**
 * 操作日志服务类 - 使用 sys_log 表
 */
class OperationLogService
{
    /**
     * 记录操作日志到 sys_log 表
     * 
     * @param string $urlName 操作名称（如：用户登录、添加用户等）
     * @param string $group 操作分组（如：登录事件、操作事件等）
     * @param string $des 操作描述
     * @param array $raw 原始数据（将被JSON编码）
     * @param int $status 状态（1:成功 0:失败）
     * @return bool
     */
    public static function log(string $urlName, string $group = '操作事件', string $des = '', array $raw = [], int $status = 1): bool
    {
        try {
            // 获取当前操作人信息
            $adminInfo = self::getCurrentAdminInfo();
            
            // 获取请求信息
            $request = Request::instance();
            $ip = self::getRealIpAddress($request);
            $url = $request->url(true);
            
            // 准备日志数据
            $data = [
                'user_id' => $adminInfo['user_id'],
                'user_name' => $adminInfo['username'],
                'url_name' => $urlName,
                'group' => $group,
                'des' => $des ?: $urlName,
                'url' => substr($url, 0, 100), // 限制长度
                'ip' => $ip,
                'raw' => json_encode($raw, JSON_UNESCAPED_UNICODE),
                'create_time' => time(),
                'update_time' => time(),
                'is_delete' => 0
            ];
            
            // 插入日志
            $result = Db::table('sys_log')->insert($data);
            
            return $result !== false;
        } catch (\Exception $e) {
            // 记录日志失败时不抛出异常，避免影响主业务
            error_log('Operation log failed: ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * 添加日志（简化版本，用于向后兼容）
     * 
     * @param string $action 操作动作
     * @param string $description 操作描述
     * @return bool
     */
    public static function addLog(string $action, string $description = ''): bool
    {
        return self::log($action, '操作事件', $description);
    }
    
    /**
     * 记录登录日志
     * 
     * @param string $username 用户名
     * @param int $status 状态（1:成功 0:失败）
     * @param string $message 消息
     * @return bool
     */
    public static function logLogin(string $username, int $status = 1, string $message = ''): bool
    {
        $des = $status ? '登录成功' : '登录失败：' . $message;
        $raw = ['username' => $username, 'status' => $status, 'message' => $message];
        return self::log('用户登录', '登录事件', $des, $raw, $status);
    }
    
    /**
     * 记录登出日志
     * 
     * @param string $username 用户名
     * @return bool
     */
    public static function logLogout(string $username): bool
    {
        $raw = ['username' => $username];
        return self::log('用户登出', '登录事件', '用户退出系统', $raw);
    }
    
    /**
     * 记录用户操作日志
     * 
     * @param string $action 操作动作（如：添加、编辑、删除）
     * @param string $module 模块名称（如：用户、角色、权限）
     * @param array $data 操作数据
     * @return bool
     */
    public static function logUserAction(string $action, string $module, array $data = []): bool
    {
        $urlName = "{$module}{$action}";
        $des = "{$action}{$module}";
        return self::log($urlName, '操作事件', $des, $data);
    }
    
    /**
     * 获取当前管理员信息
     * 
     * @return array ['user_id' => int, 'username' => string]
     */
    private static function getCurrentAdminInfo(): array
    {
        // 优先从 Session 获取管理员信息
        $adminInfo = Session::get('admin_info');
        if ($adminInfo && isset($adminInfo['id']) && isset($adminInfo['username'])) {
            return [
                'user_id' => (int)$adminInfo['id'],
                'username' => $adminInfo['username']
            ];
        }
        
        // 兼容旧版本 - 从 admin_id 和 admin_username 获取
        if (Session::has('admin_id')) {
            $userId = Session::get('admin_id');
            $username = Session::get('admin_username', 'admin');
            return [
                'user_id' => (int)$userId,
                'username' => $username
            ];
        }
        
        // 如果是 API 调用，尝试从请求头获取
        $request = Request::instance();
        $apiUser = $request->header('X-Admin-User');
        $apiUserId = $request->header('X-Admin-User-Id');
        if ($apiUser && $apiUserId) {
            return [
                'user_id' => (int)$apiUserId,
                'username' => $apiUser
            ];
        }
        
        // 返回默认值
        return [
            'user_id' => 0,
            'username' => 'Unknown'
        ];
    }
    
    /**
     * 获取操作日志列表（从 sys_log 表）
     * 
     * @param int $page 页码
     * @param int $limit 每页数量
     * @param array $where 查询条件
     * @return array
     */
    public static function getList(int $page = 1, int $limit = 20, array $where = []): array
    {
        try {
            $query = Db::table('sys_log')
                ->where('is_delete', 0)
                ->order('create_time', 'desc');
            
            // 添加查询条件
            if (!empty($where['user_name'])) {
                $query->where('user_name', 'like', '%' . $where['user_name'] . '%');
            }
            
            if (!empty($where['url_name'])) {
                $query->where('url_name', 'like', '%' . $where['url_name'] . '%');
            }
            
            if (!empty($where['group'])) {
                $query->where('group', $where['group']);
            }
            
            if (!empty($where['start_time'])) {
                $query->where('create_time', '>=', strtotime($where['start_time']));
            }
            
            if (!empty($where['end_time'])) {
                $query->where('create_time', '<=', strtotime($where['end_time']));
            }
            
            $total = $query->count();
            $list = $query->page($page, $limit)->select();
            
            // 格式化时间戳
            foreach ($list as &$item) {
                $item['create_time_format'] = date('Y-m-d H:i:s', $item['create_time']);
            }
            
            return [
                'total' => $total,
                'list' => $list,
                'page' => $page,
                'limit' => $limit
            ];
        } catch (\Exception $e) {
            error_log('Get log list failed: ' . $e->getMessage());
            return [
                'total' => 0,
                'list' => [],
                'page' => $page,
                'limit' => $limit
            ];
        }
    }
    
    /**
     * 获取今日统计
     * 
     * @return array
     */
    public static function getTodayStats(): array
    {
        try {
            $todayStart = strtotime(date('Y-m-d 00:00:00'));
            $todayEnd = strtotime(date('Y-m-d 23:59:59'));
            
            $total = Db::table('sys_log')
                ->where('is_delete', 0)
                ->where('create_time', '>=', $todayStart)
                ->where('create_time', '<=', $todayEnd)
                ->count();
            
            $operators = Db::table('sys_log')
                ->where('is_delete', 0)
                ->where('create_time', '>=', $todayStart)
                ->where('create_time', '<=', $todayEnd)
                ->group('user_name')
                ->count();
            
            return [
                'total' => $total,
                'operators' => $operators
            ];
        } catch (\Exception $e) {
            error_log('Get today stats failed: ' . $e->getMessage());
            return ['total' => 0, 'operators' => 0];
        }
    }
    
    /**
     * 获取操作类型统计
     * 
     * @param int $days 天数
     * @return array
     */
    public static function getOperationStats(int $days = 7): array
    {
        try {
            $startTime = strtotime("-{$days} days");
            
            $stats = Db::table('sys_log')
                ->field('url_name, COUNT(*) as count')
                ->where('is_delete', 0)
                ->where('create_time', '>=', $startTime)
                ->group('url_name')
                ->order('count', 'desc')
                ->select();
            
            return $stats ?: [];
        } catch (\Exception $e) {
            error_log('Get operation stats failed: ' . $e->getMessage());
            return [];
        }
    }
    
    /**
     * 清理过期日志
     * 
     * @param int $days 保留天数
     * @return int 删除数量
     */
    public static function cleanup(int $days = 30): int
    {
        try {
            $expireTime = strtotime("-{$days} days");
            
            // 软删除
            $result = Db::table('sys_log')
                ->where('create_time', '<', $expireTime)
                ->update(['is_delete' => 1, 'update_time' => time()]);
            
            return $result ?: 0;
        } catch (\Exception $e) {
            error_log('Cleanup logs failed: ' . $e->getMessage());
            return 0;
        }
    }
    
    /**
     * 获取真实IP地址
     */
    private static function getRealIpAddress($request): string
    {
        // 检查是否通过代理
        if (!empty($request->header('HTTP_X_FORWARDED_FOR'))) {
            $ip = $request->header('HTTP_X_FORWARDED_FOR');
            // 如果有多个IP，取第一个
            if (strpos($ip, ',') !== false) {
                $ip = trim(explode(',', $ip)[0]);
            }
        } elseif (!empty($request->header('HTTP_X_REAL_IP'))) {
            $ip = $request->header('HTTP_X_REAL_IP');
        } elseif (!empty($request->header('HTTP_CLIENT_IP'))) {
            $ip = $request->header('HTTP_CLIENT_IP');
        } else {
            $ip = $request->ip();
        }
        
        // 验证IP格式
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
            return $ip;
        }
        
        // 如果验证失败，使用默认IP
        return $request->ip() ?: '127.0.0.1';
    }
} 